using System;
using AntEater.ComponentModel.Validation;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Design;
using System.Diagnostics.CodeAnalysis;

namespace AntEater.ComponentModel.BuildElements
{
    /// <summary>
    /// Provides the Project build element.
    /// </summary>
    [Serializable]
    [BuildElement("Project")]
    [ChildBuildElementType(typeof(ChooseBuildElement))]
    [ChildBuildElementType(typeof(ImportBuildElement))]
    [ChildBuildElementType(typeof(ItemGroupBuildElement))]
    [ChildBuildElementType(typeof(ProjectExtensionBuildElement),MaxCount=1)]
    [ChildBuildElementType(typeof(PropertyGroupBuildElement))]
    [ChildBuildElementType(typeof(TargetBuildElement))]
    [ChildBuildElementType(typeof(UsingTaskBuildElement))]
    [Icon(typeof(ProjectBuildElement), "AntEater.ComponentModel.Resources.Project.ico")]
    public class ProjectBuildElement : ContainerBuildElementBase
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ProjectBuildElement"/> class.
        /// </summary>
        public ProjectBuildElement(BuildFileDefinition context)
            : base(context) {

            _defaultTargets = new TargetCollection(context);
            _initialTargets = new TargetCollection(context);

            _defaultTargets.CollectionChanged += new EventHandler<CollectionChangeEventArgs>(DefaultTargetsCollectionChanged);
            _initialTargets.CollectionChanged += new EventHandler<CollectionChangeEventArgs>(InitialTargetsCollectionChanged);
        }

        private TargetCollection _defaultTargets;

        /// <summary>
        /// Gets or sets the default targets.
        /// </summary>
        /// <value>The default targets.</value>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        [BuildElementProperty("DefaultTargets", false, BuildElementPropertyType.ListOfTargets)]
        [Description("Optional attribute\nThe default target or targets to be the entry point of the build if no target has been specified. Multiple targets are semi-colon (;) delimited.\nIf no default target is specified in either the DefaultTargets attribute or the MSBuild command line, the engine will execute the first target in the project file after the Import elements have been evaluated.")]
        [Category("MsBuild")]
        [Editor(typeof(Design.TargetCollectionTypeEditor), typeof(UITypeEditor))]
        public TargetCollection DefaultTargets {
            get { return _defaultTargets; }
            set { _defaultTargets = value; }
        }

        private TargetCollection _initialTargets;

        /// <summary>
        /// Gets or sets the initial targets.
        /// </summary>
        /// <value>The initial targets.</value>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        [BuildElementProperty("InitialTargets", false, BuildElementPropertyType.ListOfTargets)]
        [Description("Optional attribute.\nThe initial target or targets to be run before the targets specified in the DefaultTargets attribute or on the command line. Multiple targets are semi-colon (;) delimited.")]
        [Category("MsBuild")]
        [Editor(typeof(Design.TargetCollectionTypeEditor),typeof(UITypeEditor))]
        public TargetCollection InitialTargets {
            get { return _initialTargets; }
            set { _initialTargets = value;}
        }

        private string _xmlNamespace;

        /// <summary>
        /// Gets or sets the XML namespace.
        /// </summary>
        /// <value>The XML namespace.</value>
        [BuildElementProperty("xmlns", true, BuildElementPropertyType.String)]
        [Description("Required attribute.\nThe xmlns attribute must have the value of \"http://schemas.microsoft.com/developer/msbuild/2003\".")]
        [DisplayName("xmlns")]
        [Category("MsBuild")]
        public string XmlNamespace
        {
            get { return _xmlNamespace; }
            set {
                if (_xmlNamespace != value) {
                    _xmlNamespace = value;
                    OnPropertyChanged("XmlNamespace");
                }
            }
        }

        /// <summary>
        /// Determines whether this instance is valid.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 	<c>true</c> if this instance is valid; otherwise, <c>false</c>.
        /// </returns>
        public override bool IsValid {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Validates the specified recursive.
        /// </summary>
        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
        /// <returns></returns>
        public override ReadOnlyCollection<ValidationResult> Validate(bool recursive) {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override object Clone() {
            ProjectBuildElement newElement = base.Clone() as ProjectBuildElement;

            newElement._defaultTargets.AddRange(this._defaultTargets.Clone() as TargetCollection);
            newElement._initialTargets.AddRange(this._initialTargets.Clone() as TargetCollection);
            if (this._xmlNamespace != null) {
                newElement._xmlNamespace = this._xmlNamespace.Clone() as string;
            }

            return newElement;
        }

        /// <summary>
        /// Initials the targets collection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CollectionChangeEventArgs"/> instance containing the event data.</param>
        private void InitialTargetsCollectionChanged(object sender, CollectionChangeEventArgs e) {
            OnPropertyChanged("InitialTargets");
        }

        /// <summary>
        /// Defaults the targets collection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CollectionChangeEventArgs"/> instance containing the event data.</param>
        private void DefaultTargetsCollectionChanged(object sender, CollectionChangeEventArgs e) {
            OnPropertyChanged("DefaultTargets");
        }
    }
}
